/*
*
* MVUtils
*
* This file has some "utility" methods for other parts of the code
*
*/

// this one crops the latitude and longitude extents to fit the aspect ratio
// specified by the height and width variables
void cropLatLong() {
  
  // calculate aspect ratios of "pixel" coordinates and lat/long coordinates
  float w = width;
  float h = height;
  float arPix = w / h; // for some reason this calculation doesn't work when width and height used directly
  float lLong = longMax - longMin;
  // 112.2 / 66.14 is scaling fqctor that represents the ratio between
  // the distance represented by 1 unit of latitude and 1 unit of longitude
  // at Edmonton's coordinates
  float lLat = (latMax - latMin) * 112.2 / 66.14;
  float arLL = lLong/lLat;
  
  // now modify lat/long aspect ratio to be equal to "pixel" aspect ratio
  if (arPix < arLL) {
    
    // lat/long aspect ratio needs to be decreased; increase denominator
    float lLatNew = lLong / arPix;
    latMin = latMin - (lLatNew - lLat) * 112.2 / 66.14 / 2;
    latMax = latMax + (lLatNew - lLat) * 112.2 / 66.14 / 2;
    
  } else {
    
    // lat/long aspect ratio needs to be increased; increase numerator
    float lLongNew = lLat * arPix;
    longMin = longMin - (lLongNew - lLong) / 2;
    longMax = longMax + (lLongNew - lLong) / 2;
    
  } // if
  
} // cropLatLong method

// interpolateHSV method -- takes min, max, and value, interpolates hue, and then
// converts interpolated value to RGB and returns array of integers describing colour
int[] interpolateHSV(float mi, float ma, float val) {
  
  // initialize output array
  float[] outF = new float[3];
  int[] out = new int[3];
  
  // calculate values in terms of hue, saturation, and value
  // note: to create "rainbow" gradient, hue varied linearly between
  // 0 and 240 degrees, with saturation and lightness held at 1
  float h = (val - mi) * 240 / (ma - mi);
  
  // note: since red intuitively suggests more light, below I "flip" the
  // hue value, so that higher values get lower (ie closer to blue) hues
  if(h < 0) {
    h = 240;
  } else if(h > 240) {
    h = 0;
  } else {
    h = 240 - h;
  }
  
  float s = 1;
  // note: below is a saturation correction algorithm that some think
  // makes for a more even gradient; I personally prefer the high-saturation
  // version. Note that this code is also in Ruby because this came from another
  // project of mine that was written in Ruby.
  //if(h <= 120) {
  //s = 1 - (0.29 - 0.879 * h / 360)
  //else
  //s = 1 - 1.455 * (h / 360 - 0.33)
  //end
  
  float v = 1;
      
  // convert HSV values to RGB
  float c = v * s;
  float hP = h / 60;
  float x = c * (1 - abs(hP % 2 - 1));
      
  if((0 <= hP) && (hP < 1)) {
    //outF = { c, x, 0 };
    outF[0] = c;
    outF[1] = x;
    outF[2] = 0;
  } else if((1 <= hP) && (hP < 2)) {
    //outF = { x, c, 0 };
    outF[0] = x;
    outF[1] = c;
    outF[2] = 0;
  } else if((2 <= hP) && (hP < 3)) {
    //outF = { 0, c, x };
    outF[0] = 0;
    outF[1] = c;
    outF[2] = x;
  } else if((3 <= hP) && (hP < 4)) {
    //outF = { 0, x, c };
    outF[0] = 0;
    outF[1] = x;
    outF[2] = c;
  } else if((4 <= hP) && (hP < 5)) {
    //outF = { x, 0, c };
    outF[0] = x;
    outF[1] = 0;
    outF[2] = c;
  } else if((5 <= hP) && (hP < 6)) {
    //outF = { c, 0, x };
    outF[0] = c;
    outF[1] = 0;
    outF[2] = x;
  } else {
    //outF = { 0, 0, 0 };
    outF[0] = 0;
    outF[1] = 0;
    outF[2] = 0;
  } // if
  
  float m = v - c;
  
  for(int i = 0; i < 3; i++) {
    out[i] = int((outF[i] + m) * 255);
  } // for
          
  // return out
  return out;
  
} // interpolate HSV method
